#include "accountmanager.h"
#include "account/accountuser.h"
#include "account/accountbuddy.h"
#include "network/networkmanager.h"
#include "account/loginrequest.h"
#include "account/loginresponse.h"

#include "account/activecoderequest.h"
#include "account/activecoderesponse.h"

#include "account/makeaccountrequest.h"
#include "account/makeaccountresponse.h"

#include "appchat/profile/getfriendrequest.h"
#include "appchat/profile/getfriendresponse.h"

#include "request/recentcontactrequest.h"
#include "event/recentcontactevent.h"
#include "parser/recentcontactparser.h"

#include "service/eventservice.h"
#include "profilemanager.h"
#include "sqlite/sqlitemanager.h"
#include "sqlite/sessiontable.h"
#include "profile/multigetprofilerequest.h"
#include "profile/multigetprofileresponse.h"
#include "constantapp.h"


#include <QDebug>

using namespace Account;

AccountManager *AccountManager::m_instance = NULL;

AccountManager *AccountManager::instance(QObject *parent)
{
    if (m_instance == NULL)
        m_instance = new AccountManager(parent);
    return m_instance;
}



//##################################


bool AccountManager::login(QString userName, QString pass)
{
    LoginRequest *loginRequest = new LoginRequest(userName, pass);

    connect(loginRequest,
            &LoginRequest::responded,
            this,
            &AccountManager::onLoginResponsed);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(loginRequest)) {
        delete loginRequest;
        loginRequest = NULL;
        return false;
    }

    return true;
}
bool AccountManager::createNewAccount(QString phone, QString code)
{
    MakeAccountRequest *makeAccountRequest = new MakeAccountRequest(phone, code);

    connect(makeAccountRequest,
            &MakeAccountRequest::responded,
            this,
            &AccountManager::onMakeAccountResponsed);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(makeAccountRequest)) {
        delete makeAccountRequest;
        makeAccountRequest = NULL;
        return false;
    }

    return true;
}

bool AccountManager::getActiveCodeRequest(QString phone)
{
    ActiveCodeRequest *activeCodeRequest = new ActiveCodeRequest(phone);

    connect(activeCodeRequest,
            &ActiveCodeRequest::responded,
            this,
            &AccountManager::onGetActiveCodeResponsed);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(activeCodeRequest)) {
        delete activeCodeRequest;
        activeCodeRequest = NULL;
        return false;
    }

    return true;
}

void AccountManager::logout()
{
    emit logouted();
}


void AccountManager::aboutToLogout()
{
    emit aboutToBeLogouted();
}

void AccountManager::onGetActiveCodeResponsed(Network::HttpRequest *request)
{
    const Network::HttpRequest &constRequest = *request;
    const Network::Response &response = constRequest.response();

    const ActiveCodeResponse &activeCodeResponse = (const ActiveCodeResponse &)response;

    if(response.error() == Network::Response::Network) {
        emit notifyError(1);
        return;
    }

    emit activedCode(activeCodeResponse.error());


    request->deleteLater();
}

void AccountManager::onLoginResponsed(Network::HttpRequest *request)
{
    const Network::HttpRequest &constRequest = *request;
    const Network::Response &response = constRequest.response();


    const LoginResponse &loginResponse = (const LoginResponse &)response;
    if(response.error() == Network::Response::None) {

        _currentUserId = loginResponse.userId();
        AccountManager::instance()->init(loginResponse);
        doProcessLoginSuccess();

    } else {
        emit logined(false, loginResponse.message(), "" );
    }

    request->deleteLater();
}
void AccountManager::onMakeAccountResponsed(Network::HttpRequest *request)
{
    const Network::HttpRequest &constRequest = *request;
    const Network::Response &response = constRequest.response();


    const MakeAccountResponse &makeAccountResponse = (const MakeAccountResponse &)response;
    if(response.error() == Network::Response::None) {

        _currentUserId = makeAccountResponse.userId();
        AccountManager::instance()->init(makeAccountResponse);
        doProcessLoginSuccess();

    } else {
        emit logined(false, makeAccountResponse.message(), "" );
    }

    request->deleteLater();
}

//#############################

AccountManager::AccountManager(QObject *parent) :
    QObject(parent),
    _userProfile(NULL),
    m_getFriendRequestPage(0),
    m_recentContactRequest(NULL)
{
    // Initialize EventService
    Service::EventService::instance(this);

    setConnection();
}


void AccountManager::setConnection() const
{
    connect(Network::Manager::instance(),
            &Network::Manager::sessionKeyReady,
            this,
            &AccountManager::onSessionKeyReady);

    connect(Network::Manager::instance(),
            &Network::Manager::connected,
            this,
            &AccountManager::onWebSocketConnected);
}


void AccountManager::init(const LoginResponse& loginResponse)
{

    _session_key = loginResponse.sessionKey();
    setUserProfile(loginResponse.userId(), loginResponse.userName(), loginResponse.displayName(), loginResponse.avatar());

}

void AccountManager::init(const MakeAccountResponse& makeAccountResponse)
{

    _session_key = makeAccountResponse.sessionKey();
    setUserProfile(makeAccountResponse.userId(), makeAccountResponse.userName(), makeAccountResponse.displayName(), makeAccountResponse.avatar());
}

/**
 * @brief Manager::onWebSocketConnected
 */
void AccountManager::onWebSocketConnected()
{
    //m_user->startRequestData();

}





void AccountManager::onSessionKeyReady()
{

}

/**
 * @brief Manager::initOnlineStatus
 */
void AccountManager::initOnlineStatus()
{
    m_isOnlineStatusInitialized = false;
}




bool AccountManager::postRecentContactRequest()
{
    if (m_recentContactRequest == NULL)
        m_recentContactRequest = new RecentContactRequest(this);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(m_recentContactRequest)) {
        delete m_recentContactRequest;
        m_recentContactRequest = 0;
        return false;
    }

    return true;
}


void AccountManager::updateOnlineStatus(const OnlineStatusEvent &statusEvent)
{
    //    const OnlineStatusParser::ItemMap &onlineFriends = statusEvent.items();
    //    foreach (Buddy *buddy, m_buddies) {
    //        OnlineStatusParser::ItemMap::ConstIterator itOnline = onlineFriends.find(buddy->id());
    //        if (itOnline != onlineFriends.end()) {
    //            if (buddy->onlineStatus() == false) {
    //                buddy->changeOnlineStatus(true);
    //                if (m_isOnlineStatusInitialized)
    //                    emit onlineStatusChanged(buddy);
    //            }
    //        } else {
    //            if (buddy->onlineStatus()) {
    //                buddy->changeOnlineStatus(false);
    //                if (m_isOnlineStatusInitialized)
    //                    emit onlineStatusChanged(buddy);
    //            }
    //        }
    //    }

    //    m_isOnlineStatusInitialized = true;
}


void AccountManager::updateRecentContactTime(const RecentContactEvent &recentContactEvent)
{
    ////    AccountManager *manager = AccountManager::instance();
    ////    const RecentContactEvent::ItemList items = recentContactEvent.itemList();
    ////    foreach (RecentContactEvent::Item *item, items) {
    ////        if (item == NULL)
    ////            continue;

    ////        Buddy *searchedFriend = manager->findById(item->friendId());
    ////        if (searchedFriend != NULL) {
    ////            searchedFriend->updateLastContactTime(item->lastContactTime());
    ////        }
    ////    }

    ////    emit recentContactTimeInitialized();
}


//-------------------------------------- CLEAR DATA -----------------------------------
void AccountManager::clearData()
{
    Sqlite::SessionTable::clearTable();
    m_getFriendRequestPage = 0;
    emit dataCleared();
}






QString AccountManager::getSessionKey() {
    if(_session_key == ""){
        _session_key =  Sqlite::SessionTable::getSessionInfo().sessionKey;
    }
    return _session_key;

}

void AccountManager::postRequestGetProfile()
{

    Sqlite::SessionInfo sInfo = Sqlite::SessionTable::getSessionInfo();
    if(sInfo.sessionKey == ""){

        emit requireLogin();
        return;
    }
    _currentUserId = sInfo.useId;
    _session_key = sInfo.sessionKey;
    MultiGetProfileRequest *request = new MultiGetProfileRequest(sInfo.useId,  sInfo.sessionKey);
    connect(request, &MultiGetProfileRequest::responded,
            this, &AccountManager::onGetProfileResponse);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(request)) {
        delete request;
        request = 0;
    }
    // goi request getProfile
}

void AccountManager::onGetProfileResponse(Network::HttpRequest *request){

    MultiGetProfileRequest *constRequest = (MultiGetProfileRequest*)request;
    int err = constRequest->response().errorResponsed();
    if(err == ERROR_REQUEST_SESSION ){
        emit requireLogin();
    }
    const MultiGetProfileResponse &friendResponse = (const MultiGetProfileResponse&)(constRequest->response());

    const QList<UserProfile*> &listProfile = friendResponse.getListUserProfile();
    if(listProfile.size() == 1){
        _userProfile = listProfile[0];
        doProcessLoginSuccess();
    }
}

void AccountManager::doProcessLoginSuccess()
{
    ProfileManager::instance()->init();
    emit logined(true, "ok", _session_key);
    Network::Manager::instance()->onLogined(true, "ok", _session_key);

}

